import { parentPort, workerData } from "node:worker_threads";
import path from 'path';
import { exec } from "child_process";
import {readFile} from "node:fs/promises";
import { exists } from "./circle-common.js";
/**
 * get ccm path
 * @param {string} platform - the os platform
 * @param {string} arch - the architecture such x64, arm64.
 * @return {string} - the path of ccm
 */
function getCCMPath(platform, arch) {
  const fullpath = path.resolve('./node_modules/@lidh04/circle-chain-sdk/dist');
  //console.log("fullpath:", fullpath);
  let ccmPath = `${fullpath}/tools/${platform}/${arch}/ccm`;
  if (platform === 'windows') {
    ccmPath = `${ccmPath}.exe`;
  }
  if (!exists(ccmPath)) {
    const fullpath = path.resolve('.');
    ccmPath = `${fullpath}/tools/${platform}/${arch}/ccm`;
    if (platform === 'windows') {
      ccmPath = `${ccmPath}.exe`;
    }
    // console.log("using another filepath:", ccmPath);
    if (!exists(ccmPath)) {
      console.error("cannot find ccm tool!");
      throw new Error('ccm not found!');
    }
  }
  // console.log("ccmPath:", ccmPath);
  return ccmPath;
}


async function main() {
  const controller = new AbortController();
  const { signal } = controller;

  parentPort.once('message', (message) => {
    if (message === 'terminate') {
      controller.abort();
    }
  });

  const { platform, arch, blockHeaderHexString, threadCount, index } = workerData;
  const ccmPath = getCCMPath(platform, arch);
  try {
    const start = Math.round(100 / threadCount * index);
    const end = Math.round(100 / threadCount * (index + 1));
    const command = `${ccmPath} ${start}-${end} ${blockHeaderHexString}`;
    console.log("begin to run command: ", command);
    const data = await runCommand(command, signal);
    console.log('mine block result:', data);
    const content = await readFile('./mined.txt', { encoding: 'utf8' });
    console.log('get mined content:', content);
    parentPort.postMessage(content);
  } catch (error) {
    console.error("mine block error, index:", index, "error:", error);
    throw error;
  }
}

/**
 * run the command
 * @param {string} command - the shell command
 * @param {object} signal - the signal object
 * @returns {Promise<string>} 
 */
function runCommand(command, signal) {
  return new Promise((resolve, reject) => {
    exec(command, { signal }, (error, data) => {
      if (error) {
        reject(error);
        return;
      }
      resolve(data);
    });
  });
}

main();

